#include <stdio.h>
#include <sys/types.h>
#include <pthread.h>

#include <semaphore.h>

#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

// 自定义车辆状态结构体类型
typedef struct {
    pthread_t tid; // 线程号
    char name[64]; // 车辆名称
    int status;  // 0 初始状态,  1 入场状态  2 出场状态
} CarStaus;


// 定义全局变量： 信号量
sem_t sem1; // 入车信号量
sem_t sem2; // 出车信号量

// 定义20辆车的状态信息
CarStaus cs[20];

// 停车入场任务
void *carstop_task(void *arg){ 
    char *name = (char *)arg;
   
    sem_wait(&sem1);
     for(int i=0;i<20;i++){
        if(cs[i].tid == pthread_self()){
            cs[i].status = 1;
            break;
        }
    }

    printf("%s 入场成功\n", name);
    sleep(rand() % 6 + 5);
    sem_post(&sem2);  // 通知出场计费
  
    return NULL;
}

void *carout_task(void *arg){
    while(1){
        sem_wait(&sem2); // 等待有车辆出场信号
        for(int i=0;i<20;i++){
            if(cs[i].status == 1){
                cs[i].status = 2;
                printf("---%s 出场成功---\n", cs[i].name);
                break;
            }
        }
        sleep(1);
        sem_post(&sem1); // 通过入场的车辆可以进入了
    }
    return NULL;
}

int main(int argc, char const *argv[])
{
    srand(time(NULL));
    
    // 初始化信号量(多值信号量)
    sem_init(&sem1, 0, 10);
    sem_init(&sem2, 0, 0);

    // 创建出场计费的线程
    pthread_t tid1;
    pthread_create(&tid1, NULL, carout_task, NULL);

    // 创建20个线程（车辆）
    for(int i=0;i<20;i++){
        sprintf(cs[i].name, "陕A8%02d6%c", rand() % 90+10, rand() % 22 + 65);
        pthread_create(&cs[i].tid, NULL, carstop_task, cs[i].name);
    }

    for(int i=0;i<20;i++){
        pthread_join(cs[i].tid, NULL);
    }

    // 所有停车任务都结束了
    sleep(2);
    pthread_cancel(tid1);
    pthread_join(tid1, NULL);

    // 销毁信号量
    sem_destroy(&sem1);
    return 0;
}
